package com.dshore.messagecenter.util;

import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.dshore.messagecenter.dao.basedata.MdAppDao;
import com.dshore.messagecenter.dao.system.SysCustomProcessDao;
import com.dshore.messagecenter.dao.topicqueue.TopicQueueDao;
import com.dshore.messagecenter.dao.topicqueue.TopicSendDao;
import com.dshore.messagecenter.dao.warning.ExceptionMessageDao;
import com.dshore.messagecenter.model.msgrecord.ReceiveMsg;
import com.dshore.messagecenter.model.topicqueue.MdTopic;
import com.dshore.messagecenter.model.topicqueue.MdTopicAccess;
import com.dshore.messagecenter.model.topicqueue.MdTopicSend;
import com.dshore.messagecenter.model.warning.MrExceptionMessage;
import com.dshore.messagecenter.util.secret.AESGCMUpdateAAD2;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.rabbitmq.http.client.Client;
import com.rabbitmq.http.client.domain.ExchangeInfo;
import com.rabbitmq.http.client.domain.QueueInfo;
import com.rabbitmq.http.client.domain.UserPermissions;

@Component
public class RabbitUtil {

	private static final Logger logger = LoggerFactory.getLogger(RabbitUtil.class);
	
	@Value("${spring.rabbitmq.host}")
	private String rabbitHost;
	
	@Value("${spring.rabbitmq.httpPort}")
	private String rabbitHttpPortPort;
	
	@Value("${spring.rabbitmq.virtual-host}")
	private String vhostName;
	
	@Value("${spring.rabbitmq.username}")
	private String rabbitUsername;
	
	@Value("${spring.rabbitmq.secret}")
	private String rabbitSecret;
	
	// 有效期
	@Value("${rabbitmq.pullmsg.expiration}")
	private int pullmsgExpiration;
	
	@Autowired
	private TopicQueueDao topicQueueDao;
	
	@Autowired
	private TopicSendDao topicSendDao;
	
	@Autowired
	private MdAppDao mdAppDao;
	
	@Autowired
	private ExceptionMessageDao exceptionMessageDao;
	
	@Autowired
	private RabbitPublish rabbitPublish;
	
	@Autowired
	private SysCustomProcessDao SysCustomProcessDao;
	
	private Client client = null;
	
	/**
	 * 创建RabbitMQ用户
	 * @param username
	 * @param password
	 */
	public void createUser(String username, String password) {
		logger.info("createUser-username: " + username + ", password: " + password);
        // 新创建的user仅赋予management权限，可管理自身的vhost及exchange、queue
        List<String> permission = new ArrayList<String>();
        permission.add("management");
        // 创建用户
        getClient().createUser(username, password.toCharArray(), permission);
	}
	
	/**
	 * 删除用户
	 * @param username
	 */
	public void deleteUser(String username) {
		logger.info("deleteUser-username: " + username);
        getClient().deleteUser(username);
	}
	
	/**
	 * 发布主题队列
	 * @param topicQueueNo
	 */
	public int publishTopicQueue(String topicQueueNo) {
		// 根据主题队列编号查询主题队列相关数据
		MdTopic mdTopic = topicQueueDao.queryQueueInfo(topicQueueNo);
		List<MdTopicAccess> mdTopicAccesss = topicQueueDao.queryAccessByTopicSign(topicQueueNo);
		List<MdTopicSend> mdTopicSends = topicQueueDao.querySendByTopicSign(topicQueueNo);
		
		if (mdTopic == null || mdTopicAccesss.size() == 0 || mdTopicSends.size() == 0) {
			return 2;
		}
		
		MdTopicAccess mdTopicAccess = mdTopicAccesss.get(0);
		
		// 根据接入方式设置vhost
		if (mdTopic.getAccessType().equals("1401")) {
			// 设置vhost为系统vhost
			mdTopic.setVhostName(vhostName);
			
			// 根据是否包含模板，创建模板处理队列
			if (mdTopic.getTemplateId() != null) {
				// 如果存在模板，则先将消息发送到模板处理队列进行处理后，再发送到发送队列
				mdTopicAccess.setQueueName(getRandomName("queue-"));
			}
		} else if (mdTopic.getAccessType().equals("1402")) {
			// 创建单独的vhost
			mdTopic.setVhostName(getRandomName("vhost-"));
		}
		
		// 创建fanout类型的交换机，每个主题队列对应一个交换机
		mdTopic.setExchangeName(getRandomName("exchange-"));

		// 数据库更新内容
		List<Object[]> recordList = new ArrayList<Object[]>();
		
		// 循环目标应用，创建队列并绑定到交换机
		for (MdTopicSend mdTopicSend : mdTopicSends) {
			// 创建队列并绑定到fanout交换机
			mdTopicSend.setQueueName(getRandomName("queue-"));
			
			recordList.add(new Object[]{mdTopicSend.getQueueName(), mdTopicSend.getId()});
		}
		
		// 状态改为已发布
		mdTopic.setStatus("1302");
		
		// 判断sql是否都执行成功，执行成功后进行rabbitmq操作
		if (updateTable(mdTopic, mdTopicAccess, recordList)) {
			// 判断接入类型
			if (mdTopic.getAccessType().equals("1401")) {
				// 创建交换机
				createExchange(mdTopic.getVhostName(), mdTopic.getExchangeName());
				// 服务接入，判断是否需要创建模板处理队列
				if (mdTopicAccess.getQueueName() != null) {
					createQueue(mdTopic.getVhostName(), mdTopicAccess.getQueueName());
				}
				// 监听目标队列名称
				StringBuffer queueNames = new StringBuffer();
				// 创建发送队列并绑定
				for (MdTopicSend mdTopicSend : mdTopicSends) {
					// 发送方式为推送，则直接创建队列
					if ("1501".equals(mdTopicSend.getSendType())) {
						createQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
					} else {
						// 否则，创建包含有效期的队列
						createExpirationQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
					}
					bindQueue(mdTopic.getVhostName(), mdTopic.getExchangeName(), mdTopicSend.getQueueName());
					
					queueNames.append(mdTopicSend.getQueueName() + ",");
				}
				queueNames.deleteCharAt(queueNames.length() - 1);
				
				// 修改完成后调用更新配置接口
				rabbitPublish.addTopicQueue(mdTopic.getTopicQueueNo(), queueNames.toString());
			} else if (mdTopic.getAccessType().equals("1402")) {
				// 消息队列接入创建vhost
				createVhost(mdTopic.getVhostName());
				// 创建vhost下的交换机
				createExchange(mdTopic.getVhostName(), mdTopic.getExchangeName());
				
				// 为源应用分配写权限
				setPermission(mdTopicAccess.getQueueKey().split(",")[0], mdTopic.getVhostName(), 1);

				for (MdTopicSend mdTopicSend : mdTopicSends) {
					createQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
					bindQueue(mdTopic.getVhostName(), mdTopic.getExchangeName(), mdTopicSend.getQueueName());
					// 为所有目标应用设置读权限
					setPermission(mdTopicSend.getQueueKey().split(",")[0], mdTopic.getVhostName(), 0);
				}
			}
			
			return 1;
		} else {
			return 0;
		}
	}
	
	/**
	 * 更新数据库
	 * @param mdTopic
	 * @param mdTopicAccess
	 * @param recordList
	 * @return
	 */
	@Transactional
	public boolean updateTable(MdTopic mdTopic,MdTopicAccess mdTopicAccess,List<Object[]> recordList) {

		// 修改数据库，更新所有创建的队列和交换机，状态改为已发布
		Integer num1 = topicQueueDao.updateQueueVE(mdTopic.getVhostName(), mdTopic.getExchangeName(), mdTopic.getStatus(), mdTopic.getId());
		Integer num2 = topicQueueDao.updateAccessQueueName(mdTopicAccess.getQueueName(), mdTopicAccess.getId());
		Integer num3 = topicQueueDao.updateSendQueueName(recordList);
		
		if (num1 != null && num2 != null && num3 != null && num1 > 0 && num2 > 0 && num3 > 0) {
			return true;
		}else {
			return false;
		}
	}
	
	/**
	 * 撤回主题队列
	 * @param topicQueueNo
	 */
	public int revocationTopicQueue(String topicQueueNo) {
		// 根据主题队列编号查询主题队列相关数据
		MdTopic mdTopic = topicQueueDao.queryQueueInfo(topicQueueNo);
		List<MdTopicAccess> mdTopicAccesss = topicQueueDao.queryAccessByTopicSign(topicQueueNo);
		List<MdTopicSend> mdTopicSends = topicQueueDao.querySendByTopicSign(topicQueueNo);
		
		if (mdTopic == null || mdTopicAccesss.size() == 0 || mdTopicSends.size() == 0) {
			return 2;
		}
		
		MdTopicAccess mdTopicAccess = mdTopicAccesss.get(0);

		// 数据库更新内容
		List<Object[]> recordList = new ArrayList<Object[]>();
		
		// 删除vhost名称
		String vhostName = null;
		// 删除交换机名称
		String exchangeName = null;
		// 删除模板队列名称
		String templateQueue = null;
		// 取消监听目标队列名称
		StringBuffer queueNames = new StringBuffer();
		
		// 当接入方式为服务接入时
		if (mdTopic.getAccessType().equals("1401")) {
			vhostName = mdTopic.getVhostName();
			// 清除vhost
			mdTopic.setVhostName(null);
			if (mdTopic.getExchangeName() != null) {
				exchangeName = mdTopic.getExchangeName();
				mdTopic.setExchangeName(null);
			}
			if (mdTopicAccess.getQueueName() != null) {
				templateQueue = mdTopicAccess.getQueueName();
				mdTopicAccess.setQueueName(null);
			}

			for (MdTopicSend mdTopicSend : mdTopicSends) {
				if (mdTopicSend.getQueueName() != null) {
					queueNames.append(mdTopicSend.getQueueName() + ",");
					mdTopicSend.setQueueName(null);
					recordList.add(new Object[]{mdTopicSend.getQueueName(), mdTopicSend.getId()});
				}
			}
			if (queueNames.length() > 0) {
				queueNames.deleteCharAt(queueNames.length() - 1);
			}
			System.out.println(queueNames);
		} else if (mdTopic.getAccessType().equals("1402")) { // 当接入方式为消息队列接入时
			vhostName = mdTopic.getVhostName();
			// 将配置全部置为空
			mdTopic.setVhostName(null);
			mdTopic.setExchangeName(null);
			mdTopicAccess.setQueueName(null);
			
			for (MdTopicSend mdTopicSend : mdTopicSends) {
				mdTopicSend.setQueueName(null);
				
				recordList.add(new Object[]{mdTopicSend.getQueueName(), mdTopicSend.getId()});
			}
		}
		
		// 状态改为未发布
		mdTopic.setStatus("1301");
		
		// 判断修改是否成功
		if (updateTable(mdTopic, mdTopicAccess, recordList)) {
			if (mdTopic.getAccessType().equals("1401")) {
				// 修改完成后调用更新配置接口
				rabbitPublish.removeTopicQueue(mdTopic.getTopicQueueNo(), queueNames.toString());
				
				if (exchangeName != null) {
					deleteExchange(vhostName, exchangeName);
				}
				if (templateQueue != null) {
					deleteQueue(vhostName, templateQueue);
				}
				for (String queueName : queueNames.toString().split(",")) {
					if (queueName != null) {
						deleteQueue(vhostName, queueName);
					}
				}
			} else if (mdTopic.getAccessType().equals("1402")) {
				// 删除单独的vhost，相应的exchange和queue将全部被删除
				if (vhostName != null) {
					deleteVhost(vhostName);
				}
			}
			return 1;
		} else {
			return 0;
		}
	}
	
	/**
	 * 更新主题队列，添加/删除目标应用
	 * @param topicQueueNo
	 */
	public boolean updateTargetApp (String topicQueueNo, List<Map<String,String>> targetList) {
		// 获取主题队列配置
		MdTopic mdTopic = topicQueueDao.queryQueueInfo(topicQueueNo);
		// 根据主题队列编号查询现有目标应用
		List<MdTopicSend> mdTopicSends = topicQueueDao.querySendByTopicSign(topicQueueNo);
		
		// 保存旧和新目标应用交集
		Map<String, MdTopicSend> oldMpTopicSendList = new HashMap<String, MdTopicSend>();
		// 保存新目标应用
		Map<String, MdTopicSend> newMpTopicSendList = new HashMap<String, MdTopicSend>();
		// 保存将被删除的目标应用
		List<MdTopicSend> removeMpTopicSendList = new ArrayList<MdTopicSend>();
		// 保存将要新增的目标应用
		List<MdTopicSend> addMpTopicSendList = new ArrayList<MdTopicSend>();
		
		// 循环新目标应用列表，转为map
		for (Map<String,String> targetApp : targetList) {
			MdTopicSend mdTopicSend =new MdTopicSend();
			mdTopicSend.setTargetAppId(targetApp.get("targetId"));
			if (mdTopic.getAccessType().equals("1401")) {
				mdTopicSend.setSendType(targetApp.get("sendType"));
				mdTopicSend.setTargetUrl(targetApp.get("sendChannel"));
			}
			// 存入新目标应用map
			newMpTopicSendList.put(mdTopicSend.getTargetAppId() + mdTopicSend.getSendType() + mdTopicSend.getTargetUrl(), mdTopicSend);
		}
		
		int seq = 0;
		// 循环旧目标应用列表，得出与新目标应用的交集和被删除的目标应用
		for (MdTopicSend mdTopicSend : mdTopicSends) {
			// 当新的目标应用列表中没有时，放入删除map
			if (!newMpTopicSendList.containsKey(mdTopicSend.getTargetAppId() + mdTopicSend.getSendType() + mdTopicSend.getTargetUrl())) {
				removeMpTopicSendList.add(mdTopicSend);
			} else {
				// 当在新目标应用列表中存在时，放入交集map
				oldMpTopicSendList.put(mdTopicSend.getTargetAppId() + mdTopicSend.getSendType() + mdTopicSend.getTargetUrl(), mdTopicSend);
			}
			
			if (seq < mdTopicSend.getSeq()) {
				seq = mdTopicSend.getSeq();
			}
		}
		// 循环新目标应用，获取新增的目标应用
		for (Map<String,String> targetApp : targetList) {
			// 当不存在与交集map中时，为新增的目标应用
			if (!oldMpTopicSendList.containsKey(targetApp.get("targetId") + targetApp.get("sendType") + targetApp.get("sendChannel"))) {
				MdTopicSend mdTopicSend = newMpTopicSendList.get(targetApp.get("targetId") + targetApp.get("sendType") + targetApp.get("sendChannel"));
				mdTopicSend.setId(UUIDUtil.getUUId());
				mdTopicSend.setTopicQueueNo(topicQueueNo);
				mdTopicSend.setQueueName(getRandomName("queue-"));
				mdTopicSend.setDelFlag(0);
				seq++;
				mdTopicSend.setSeq(seq);
				addMpTopicSendList.add(mdTopicSend);
			}
		}
		
		// 新增目标应用
		int[] addNums = topicSendDao.saveTopicSend(addMpTopicSendList);
		// 删除目标应用
		int[] removeNums = topicSendDao.deleteTopicSend(removeMpTopicSendList);
		if (addNums.length > 0 || removeNums.length > 0 ) {
			// 取消监听目标队列名称
			StringBuffer removeQueueNames = new StringBuffer();
			// 添加监听目标队列名称
			StringBuffer addQueueNames = new StringBuffer();
			for (MdTopicSend mdTopicSend : removeMpTopicSendList) {
				removeQueueNames.append(mdTopicSend.getQueueName() + ",");
				deleteQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
				
				// 消息队列接入时，清除权限
				if (mdTopic.getAccessType().equals("1402")) {
					// 为新增目标应用设置读权限
					clearPermission(mdTopicSend.getQueueKey().split(",")[0], mdTopic.getVhostName());
				}
			}
			for (MdTopicSend mdTopicSend : addMpTopicSendList) {
				addQueueNames.append(mdTopicSend.getQueueName() + ",");
				// 发送方式为推送，则直接创建队列
				if ("1501".equals(mdTopicSend.getSendType())) {
					createQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
				} else {
					// 否则，创建包含有效期的队列
					createExpirationQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
				}
				bindQueue(mdTopic.getVhostName(), mdTopic.getExchangeName(), mdTopicSend.getQueueName());
				
				// 消息队列接入时，配置权限
				if (mdTopic.getAccessType().equals("1402")) {
					// TODO 可优化，此处为循环查询，为新增目标应用设置读权限
					setPermission(mdAppDao.selectByqueuekey(mdTopicSend.getTargetAppId()).getQueueKey().split(",")[0], mdTopic.getVhostName(), 0);
				}
			}
			// 服务接入时，调用发布订阅通道，通知服务端更新目标应用配置
			if (mdTopic.getAccessType().equals("1401")) {
				if (removeQueueNames.length() > 0) {
					removeQueueNames.deleteCharAt(removeQueueNames.length() - 1);
					rabbitPublish.removeTargetApp(removeQueueNames.toString());
				}
				if (addQueueNames.length() > 0) {
					addQueueNames.deleteCharAt(addQueueNames.length() - 1);
					rabbitPublish.addTargetApp(addQueueNames.toString());
				}
			}
		}
		
		return true;
	}
	
	/**
	 * 异常消息手动重发
	 * @param topicQueueNo
	 * @param appNo
	 * @return
	 */
	@Transactional
	public boolean msgResend(String topicQueueNo, String appCode) {
		// 根据主题队列编号查询主题队列相关数据
		MdTopic mdTopic = topicQueueDao.queryQueueInfo(topicQueueNo);
		// 主题队列未发布或接入方式为消息队列接入，不支持重发
		if (mdTopic.getStatus().equals("1301") || mdTopic.getAccessType().equals("1402")) {
			return false;
		}
		// 根据主题队列编号和应用编号，查询指定目标应用配置
		List<MdTopicSend> mdTopicSends = topicSendDao.querySendData(topicQueueNo, appCode);
		// 如果没有目标应用，则返回错误
		if (mdTopicSends.size() == 0) {
			return false;
		}
		
		// 将异常消息转为消息接受类
		List<ReceiveMsg> receiveMsgs = new ArrayList<ReceiveMsg>();
		try {
			for (MrExceptionMessage message : exceptionMessageDao.queryData(topicQueueNo, appCode)) {
				ReceiveMsg receiveMsg = new ReceiveMsg();
				receiveMsg.setTopicQueueNo(topicQueueNo);
				String messageContent = new String(message.getMessageContent().getBytes(1, (int) message.getMessageContent().length()));
				receiveMsg.setMessageId(messageContent.split("&&")[0]);
				receiveMsg.setMessageBody(messageContent.split("&&")[1]);
				receiveMsgs.add(receiveMsg);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		}
		exceptionMessageDao.deleteAfterResend(topicQueueNo, appCode);
		
		if (mdTopicSends.get(0).getQueueName() == null || 
				getClient().getQueue(mdTopic.getVhostName(), mdTopicSends.get(0).getQueueName()) == null) {
			return false;
		} else {
			rabbitPublish.msgResend(mdTopicSends.get(0).getQueueName(),receiveMsgs);
			
			return true;
		}
	}
	
	/**
	 * 主题队列配置手动同步
	 * @param topicQueueNo
	 * @return
	 */
	public boolean configSync(String topicQueueNo) {
		// 根据主题队列编号查询主题队列相关数据
		MdTopic mdTopic = topicQueueDao.queryQueueInfo(topicQueueNo);
		List<MdTopicAccess> mdTopicAccesss = topicQueueDao.queryAccessByTopicSign(topicQueueNo);
		List<MdTopicSend> mdTopicSends = topicQueueDao.querySendByTopicSign(topicQueueNo);
		
		// 当查询无结果或主题队列状态为未发布，返回错误
		if (mdTopic == null || mdTopicAccesss.size() == 0 || mdTopicSends.size() == 0
				|| mdTopic.getStatus().equals("1301")) {
			return false;
		}
		
		// 当vhost或交换机为空，返回失败
		if (mdTopic.getVhostName() == null || mdTopic.getVhostName().equals("") || 
				mdTopic.getExchangeName() == null || mdTopic.getExchangeName().equals("")) {
			return false;
		}
		// 监听目标队列名称
		StringBuffer queueNames = new StringBuffer();
		// 循环目标应用列表，当队列名称为空，返回失败，否则记录队列名称
		for (MdTopicSend mdTopicSend : mdTopicSends) {
			if (mdTopicSend.getQueueName() == null || mdTopicSend.getQueueName().equals("")) {
				return false;
			} else {
				queueNames.append(mdTopicSend.getQueueName() + ",");
			}
		}
		queueNames.deleteCharAt(queueNames.length() - 1);
		
		MdTopicAccess mdTopicAccess = mdTopicAccesss.get(0);
		
		// 服务接入需要通知服务端更新
		if (mdTopic.getAccessType().equals("1401")) {
			// 检查vhost、交换机和队列是否创建
			if (getClient().getVhost(mdTopic.getVhostName()) == null) {
				createVhost(mdTopic.getVhostName());
			}
			if (getClient().getExchange(mdTopic.getVhostName(), mdTopic.getExchangeName()) == null) {
				createExchange(mdTopic.getVhostName(), mdTopic.getExchangeName());
			}
			if (mdTopicAccess.getQueueName() != null && mdTopicAccess.getQueueName().equals("") && 
					getClient().getQueue(mdTopic.getVhostName(), mdTopicAccess.getQueueName()) == null) {
				createQueue(mdTopic.getVhostName(), mdTopicAccess.getQueueName());
			}
			for (MdTopicSend mdTopicSend : mdTopicSends) {
				if (getClient().getQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName()) == null) {
					// 发送方式为推送，则直接创建队列
					if ("1501".equals(mdTopicSend.getSendType())) {
						createQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
					} else {
						// 否则，创建包含有效期的队列
						createExpirationQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
					}
				}
				// 进行一次交换机绑定，防止有队列未绑定
				bindQueue(mdTopic.getVhostName(), mdTopic.getExchangeName(), mdTopicSend.getQueueName());
			}
			rabbitPublish.addTopicQueue(mdTopic.getTopicQueueNo(), queueNames.toString());
			return true;
		} if (mdTopic.getAccessType().equals("1402")) { // 消息队列接入需要配置权限
			// 检查vhost、交换机和队列是否创建
			if (getClient().getVhost(mdTopic.getVhostName()) == null) {
				createVhost(mdTopic.getVhostName());
			}
			if (getClient().getExchange(mdTopic.getVhostName(), mdTopic.getExchangeName()) == null) {
				createExchange(mdTopic.getVhostName(), mdTopic.getExchangeName());
			}
			if (mdTopicAccess.getQueueName() != null && mdTopicAccess.getQueueName().equals("") && 
					getClient().getQueue(mdTopic.getVhostName(), mdTopicAccess.getQueueName()) == null) {
				createQueue(mdTopic.getVhostName(), mdTopicAccess.getQueueName());
			}
			// 为源应用分配写权限
			setPermission(mdTopicAccess.getQueueKey().split(",")[0], mdTopic.getVhostName(), 1);
			// 循环目标应用，进行交换机绑定并设置权限
			for (MdTopicSend mdTopicSend : mdTopicSends) {
				if (getClient().getQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName()) == null) {
					createQueue(mdTopic.getVhostName(), mdTopicSend.getQueueName());
				}
				bindQueue(mdTopic.getVhostName(), mdTopic.getExchangeName(), mdTopicSend.getQueueName());
				// 为所有目标应用设置读权限
				setPermission(mdTopicSend.getQueueKey().split(",")[0], mdTopic.getVhostName(), 0);
			}
			return true;
		}
		
		return false;
	}
	
	/**
	 * 创建vhost
	 * @param vhostName
	 */
	private void createVhost(String vhostName) {
		logger.info("createVhost-vhostName: " + vhostName);
		try {
			getClient().createVhost(vhostName);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 删除vhost
	 * @param vhostName
	 */
	private void deleteVhost(String vhostName) {
		logger.info("deleteVhost-vhostName: " + vhostName);
		getClient().deleteVhost(vhostName);
	}
	
	/**
	 * 为用户分配权限
	 * @param username
	 * @param vhostName
	 * @param readOrWrite 0 只读，1 只写，2 所有权限
	 */
	private void setPermission(String username, String vhostName, int readOrWrite) {
		logger.info("setPermission-username: " + username + ", vhostName: " + vhostName + ", readOrWrite: " + readOrWrite);
        UserPermissions userPermissions = new UserPermissions();
        // 只读权限
        if (readOrWrite == 0) {
            userPermissions.setConfigure("");
            userPermissions.setRead(".*");
            userPermissions.setWrite("");
        }else if (readOrWrite == 1) { // 只写权限
            userPermissions.setConfigure("");
            userPermissions.setRead("");
            userPermissions.setWrite(".*");
        }else if (readOrWrite == 2) { // 所有权限
            userPermissions.setConfigure(".*");
            userPermissions.setWrite(".*");
            userPermissions.setRead(".*");
        }
		getClient().updatePermissions(vhostName, username, userPermissions);
	}
	
	/**
	 * 清除权限
	 * @param username
	 * @param vhostName
	 */
	private void clearPermission(String username, String vhostName) {
		logger.info("clearPermission-username: " + username + ", vhostName: " + vhostName);
		getClient().clearPermissions(vhostName, username);
	}
	
	/**
	 * 获取队列名称
	 * @return
	 */
	private String getRandomName(String perfix) {
		return perfix + UUIDUtil.getUUId();
	}
	
	/**
	 * 创建队列
	 * @param vhostName
	 * @param queueName
	 */
	private void createQueue(String vhostName, String queueName) {
		logger.info("createQueue-vhostName: " + vhostName + ", queueName: " + queueName);
		QueueInfo queueInfo = new QueueInfo();
        queueInfo.setDurable(true);
		getClient().declareQueue(vhostName, queueName, queueInfo);
	}
	
	/**
	 * 设置拉取队列，用于主动拉取
	 * @param vhostName
	 * @param queueName
	 */
	private void createExpirationQueue(String vhostName, String queueName) {
		logger.info("createQueue-vhostName: " + vhostName + ", queueName: " + queueName);
		QueueInfo queueInfo = new QueueInfo();
        queueInfo.setDurable(true);
        Map<String,Object> map = new HashMap<String, Object>();
        map.put("x-message-ttl", pullmsgExpiration);
        queueInfo.setArguments(map);
		getClient().declareQueue(vhostName, queueName, queueInfo);
	}
	
	/**
	 * 删除队列
	 * @param vhostName
	 * @param queueName
	 */
	private void deleteQueue(String vhostName, String queueName) {
		logger.info("deleteQueue-vhostName: " + vhostName + ", queueName: " + queueName);
		getClient().deleteQueue(vhostName, queueName);
	}
	
	/**
	 * 创建交换机，只创建fanout类型交换机，用于一对多发布订阅
	 * @param vhostName
	 * @param exchangeName
	 */
	private void createExchange(String vhostName, String exchangeName) {
		logger.info("createExchange-vhostName: " + vhostName + ", exchangeName: " + exchangeName);
		ExchangeInfo exchangeInfo = new ExchangeInfo();
		exchangeInfo.setType("fanout");
		exchangeInfo.setDurable(true);
		getClient().declareExchange(vhostName, exchangeName, exchangeInfo);
	}
	
	/**
	 * 删除交换机
	 * @param vhostName
	 * @param exchangeName
	 */
	private void deleteExchange(String vhostName, String exchangeName) {
		logger.info("deleteExchange-vhostName: " + vhostName + ", exchangeName: " + exchangeName);
		getClient().deleteExchange(vhostName, exchangeName);
	}
	
	/**
	 * 队列与交换机绑定
	 * @param vhostName
	 * @param exchangeName
	 * @param queueName
	 */
	private void bindQueue(String vhostName, String exchangeName, String queueName) {
		logger.info("bindQueue-vhostName: " + vhostName + ", queueName: " + queueName + ", exchangeName: " + exchangeName);
		getClient().bindQueue(vhostName, queueName, exchangeName, "test");
	}
	
	/**
	 * 获取RabbitMQ连接
	 * @return
	 */
	public Client getClient() {
		if (client == null) {
			try {
				String pass = "";
				try {
					String publicKey = SysCustomProcessDao.selectPublicKey();
					pass = AESGCMUpdateAAD2.decript(publicKey, rabbitSecret);
				} catch (Exception e) {
					e.printStackTrace();
				}
				client = new Client("http://"+rabbitHost+":"+rabbitHttpPortPort+"/api/", rabbitUsername, pass);
				return client;
			} catch (MalformedURLException | URISyntaxException e) {
				// 创建失败时应做异常处理
				e.printStackTrace();
				return null;
			}
		}else {
			return client;
		}
	}
}
